package pe.com.casadesign.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.stereotype.Repository;

import pe.com.casadesign.dao.ComponenteDAO;
import pe.com.casadesign.domain.Componente;
import pe.com.casadesign.domain.ListaComponente;

/**
 * Implementacion de ComponenteDAO.
 * 
 * @author Pedro Vera
 * 
 */
@Repository
public class ComponenteDAOImpl implements ComponenteDAO {
	private static final Logger logger = LoggerFactory.getLogger(ComponenteDAOImpl.class);
	
	// Nombre Procedimientos Almacenados
	private static String SP_LISTAR_COMPONENTE = "SP_LISTAR_COMPONENTE";
	private static String SP_OBTENER_COMPONENTE = "SP_OBTENER_COMPONENTE";
	private static String SP_REGISTRAR_COMPONENTE = "SP_REGISTRAR_COMPONENTE";
	private static String SP_MODIFICAR_COMPONENTE = "SP_MODIFICAR_COMPONENTE";
	private static String SP_ELIMINAR_COMPONENTE = "SP_ELIMINAR_COMPONENTE";

	// Parametros de Entrada
	private static String PARAM_CODCOMPONENTE = "p_codcomponente";
	private static String PARAM_DESCRIPCION = "p_descripcion";
	private static String PARAM_ESTADO = "p_estado";
	
	// Parametros de Salida
	private static String CODCOMPONENTE = "CODCOMPONENTE";
	private static String DESCRIPCION = "DESCRIPCION";
	private static String ESTADO = "ESTADO";
	private static String FECHAREGISTRO = "FECHAREGISTRO";
	
	private static String LISTADO = "LISTADO";
	
	private static String TOTAL_FILAS_AFECTADAS = "#update-count-1";
	
	private JdbcTemplate jdbcTemplate;

	@Autowired
    public void setDataSource(DataSource dataSource)
    {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
		
	@Override
	public ListaComponente listarComponente(Componente componente) {
		logger.info("listarComponente");

		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_LISTAR_COMPONENTE).
	    						  returningResultSet(LISTADO, new RowMapper<Componente>(){
									@Override
									public Componente mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Componente componente = new Componente();
								        componente.setCodigo(rs.getInt(CODCOMPONENTE));
								        componente.setDescripcion(rs.getString(DESCRIPCION));
								        componente.setEstado(rs.getString(ESTADO));
								        componente.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return componente;
								    }
	    						  }
								);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_DESCRIPCION, componente.getDescripcion())
	    								.addValue(PARAM_ESTADO, componente.getEstado()); 

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Componente> listaComponente= (List<Componente>)data.get(LISTADO);
        
		// Instanciando objeto ListaComponente
		ListaComponente listaComponenteResultado = new ListaComponente();
        // Estableciendo resultado al objeto listaComponenteResultado
		listaComponenteResultado.setLista(listaComponente);
        
        if (logger.isDebugEnabled() && listaComponenteResultado != null)
        {
            logger.debug("size=" + listaComponenteResultado.size());
        }
        return listaComponenteResultado;
	}

	@Override
	public Componente obtenerComponente(Componente componente) {
		logger.info("obtenerComponente");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_OBTENER_COMPONENTE).
								  returningResultSet(LISTADO, new RowMapper<Componente>(){
									@Override
									public Componente mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Componente componente = new Componente();
								        componente.setCodigo(rs.getInt(CODCOMPONENTE));
								        componente.setDescripcion(rs.getString(DESCRIPCION));
								        componente.setEstado(rs.getString(ESTADO));
								        componente.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return componente;
								    }
								  }
								);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODCOMPONENTE, componente.getCodigo());

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Componente> listaComponente= (List<Componente>)data.get(LISTADO);
        
		// Declarando objeto componente Obtenido
		Componente componenteObtenido = null;
		
		if (listaComponente != null && listaComponente.size()>0){
			// Obteniendo el primer elemento de la lista de componente
			componenteObtenido = listaComponente.get(0);
		}
        
        if (logger.isDebugEnabled() && listaComponente != null)
        {
            logger.debug("size=" + listaComponente.size());
        }
        
		return componenteObtenido;
	}

	@Override
	public boolean registrarComponente(Componente componente) {
		logger.info("registrarComponente");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_REGISTRAR_COMPONENTE);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_DESCRIPCION, componente.getDescripcion())
	    								.addValue(PARAM_ESTADO, componente.getEstado());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    // Estableciendo codigo generado al objeto componente
	    int codigoComponente = (Integer)data.get(PARAM_CODCOMPONENTE);
	    
	    componente.setCodigo(codigoComponente);
	    
	    return totalRegistrosAfectado > 0;
	}

	@Override
	public boolean modificarComponente(Componente componente) {
		logger.info("modificarComponente");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_MODIFICAR_COMPONENTE);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODCOMPONENTE, componente.getCodigo())
	    								.addValue(PARAM_DESCRIPCION, componente.getDescripcion())
	    								.addValue(PARAM_ESTADO, componente.getEstado());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    return totalRegistrosAfectado > 0;
	}

	@Override
	public boolean eliminarComponente(Componente componente) {
		logger.info("eliminarComponente");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_ELIMINAR_COMPONENTE);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODCOMPONENTE, componente.getCodigo());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    return totalRegistrosAfectado > 0;
	}

}
